﻿<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue'
import { Modal as AModal, TreeSelectProps } from 'ant-design-vue'
import { BasicTableColumn } from '@/types'
import {
  Role,
  RoleAddType,
  RoleEditType,
} from '@/types/modules/role'
import { getEnumDisplayName } from '@/utils/enum'
import { formatToDateTime } from '@/utils/dateUtil'
import { useI18n } from '@/hooks/web/useI18n'
import { useHttp } from '@/hooks/web/useHttp'
import { useModal } from '@/hooks/system/useModal'
import { BasicModal as BModal } from '@/components/Modal'
import { useDrawer } from '@/hooks/system/useDrawer'
import { useTableList } from '@/hooks/system/useTableList'
import * as api from '@/api/modules/role'
import list from './components/list.vue'
import add from './add.vue'
import edit from './edit.vue'
import detail from './detail.vue'

const { t } = useI18n()

const searchParams = reactive({})

let basicData: BasicTableColumn<Role>[] = [
  {
    title: '角色码',
    dataIndex: 'roleCode',
    ellipsis: true
  },
  {
    title: '角色名称',
    dataIndex: 'name',
    ellipsis: true
  },
  {
    title: 'API权限',
    align: 'left',
    dataIndex: 'apiPermissions',
    ellipsis: true
  },
  {
    title: '视图权限',
    align: 'left',
    dataIndex: 'routePermissions',
    ellipsis: true
  },
]

const { columns, pageParams, tableData, total, getData } =
  useTableList<Role>(basicData)

const apiTreeData = ref<TreeSelectProps['treeData']>();
const routeTreeData = ref<TreeSelectProps['treeData']>();

onMounted(async () => {
  getDataList()

  apiTreeData.value = await getApiPermissionsTreeData();
  routeTreeData.value = await getRoutePermissionsTreeData();
})

const getApiPermissionsTreeData = async (): Promise<TreeSelectProps['treeData']> => {
  let perms = await api.getApiPermissions();

  if (perms.data == undefined) {
    return;
  }

  let data = new Array<TreeSelectProps['treeData']>();

  perms.data.forEach(e => {
    let module = new Object();

    module.title = e.controllerDisplayName
    module.value = e.controller
    module.children = new Array<TreeSelectProps['treeData']>();

    for (let apiKey in e.apiInfo) {
      let api = new Object();
      api.title = e.apiInfo[apiKey];
      api.value = apiKey;

      module.children.push(api)
    }

    data.push(module)
  })

  return data as TreeSelectProps['treeData'];
}

const getRoutePermissionsTreeData = async (): Promise<TreeSelectProps['treeData']> => {
  let perms = await api.getRoutePermissions();

  if (perms.data == undefined) {
    return;
  }

  let data = new Array<TreeSelectProps['treeData']>();

  perms.data.forEach(e => {
    let module = new Object();

    module.title = e.controllerDisplayName
    module.value = e.name

    data.push(module)
  })

  return data as TreeSelectProps['treeData'];
}

const getDataList = getData(api.getRolePage, searchParams)

const addFormRef = ref()
const {
  bindValue: addBindValue,
  register: addRegister,
  onShow: onShowAdd,
  onClose: onCloseAdd,
  getInnerForm: getAddForm
} = useModal<Role>()
const handleAddResult = useHttp(
  t('system.api.addError'),
  t('system.api.addSuccess')
)
const onFinishAdd = async function () {
  const result = await getAddForm<RoleAddType>(addFormRef)
  if (result) {
    const res = await api.createRole(result)
    handleAddResult(res, () => {
      getDataList()
      onCloseAdd()
    })
  }
}

const editFormRef = ref()
const {
  bindValue: editBindValue,
  register: editRegister,
  currentItem: editCurrentItem,
  onShow: onShowEdit,
  onClose: onCloseEdit,
  getInnerForm: getEditForm
} = useModal<Role>()
const handleEditResult = useHttp(
  t('system.api.editError'),
  t('system.api.editSuccess')
)
const onFinishEdit = async function () {
  const result = await getEditForm<RoleEditType>(editFormRef)
  if (result) {
    const res = await api.updateRole(result, editCurrentItem.value?.id)
    handleEditResult(res, () => {
      getDataList()
      onCloseEdit()
    })
  }
}

const {
  visible: detailVisible,
  currentItem: detailCurrentItem,
  onChange: onChangeDetail,
  onClose: onCloseDetail
} = useModal()

const deleteDataHttp = useHttp(
  t('system.api.deleteError'),
  t('system.api.deleteSuccess')
)
const hanldeDeleteData = async (role: Role) => {
  const res = await api.deleteRole(role.id)
  deleteDataHttp(res, getDataList)
}
</script>

<template>
  <div class="user-page">
    <a-card class="table-card">
      <list v-bind="{ pageParams, total, columns, tableData, apiTreeData, routeTreeData }" title="角色" @add="onShowAdd" @refresh="getDataList">
        <template #operate="row">
          <a type="link" @click="onChangeDetail(row)">{{ t('system.detail') }}</a>
          <a-divider type="vertical" />
          <a type="link" @click="onShowEdit(row)">{{ t('system.edit') }}</a>
          <a-divider type="vertical" />
          <a-popconfirm :title="t('system.deletePrompt')" placement="left" @confirm="hanldeDeleteData(row)">
            <a type="link" class="ap-action-danger-btn">{{
              t('system.delete')
              }}</a>
          </a-popconfirm>
        </template>
      </list>
    </a-card>

    <b-modal v-bind="addBindValue" :title="t('system.modal.add')" @register="addRegister" @ok="onFinishAdd">
      <add ref="addFormRef" :api-tree-data="apiTreeData" :route-tree-data="routeTreeData" />
    </b-modal>

    <b-modal v-bind="editBindValue" :title="t('system.modal.edit')" @register="editRegister" @ok="onFinishEdit">      
      <edit ref="editFormRef" :item-data="editCurrentItem" :api-tree-data="apiTreeData" :route-tree-data="routeTreeData" />
    </b-modal>

    <b-modal v-if="detailVisible" v-model:visible="detailVisible" width="50%"
      :bodyStyle="{ overflow: 'auto', maxHeight: '78vh', padding: 0 }" :footer="null" @cancel="onCloseDetail">
      <template #title>
        <div class="drawer-footer">
          <div>{{ t('system.modal.detail') }}</div>
        </div>
      </template>
      <detail :item-data="detailCurrentItem" :api-tree-data="apiTreeData" :route-tree-data="routeTreeData" />
    </b-modal>
  </div>
</template>

<style lang="less" scoped>
.user-page {
  padding: 20px;

  .search-card .ant-card-body {
    padding-bottom: 0;
  }

  .table-card {
    padding-bottom: 20px;
    margin: 20px 0;
  }
}

.drawer-footer {
  button {
    margin-left: 8px;
  }
}
</style>
